package main

import (
	"encoding/json"
	"fmt"
	"github.com/gogf/gf/os/gtime"
	"github.com/tidwall/gjson"
)

type Table struct {
	TableName      string      `orm:"table_name"       json:"table_name"`      // 表名称
	TableComment   string      `orm:"table_comment"    json:"table_comment"`   // 表描述
	ClassName      string      `orm:"class_name"       json:"class_name"`      // 实体类名称
	TplCategory    string      `orm:"tpl_category"     json:"tpl_category"`    // 使用的模板（crud单表操作 tree树表操作）
	PackageName    string      `orm:"package_name"     json:"package_name"`    // 生成包路径
	ModuleName     string      `orm:"module_name"      json:"module_name"`     // 生成模块名
	BusinessName   string      `orm:"business_name"    json:"business_name"`   // 生成业务名
	FunctionName   string      `orm:"function_name"    json:"function_name"`   // 生成功能名
	FunctionAuthor string      `orm:"function_author"  json:"function_author"` // 生成功能作者
	Options        string      `orm:"options"          json:"options"`         // 其它生成选项
	CreateBy       string      `orm:"create_by"        json:"create_by"`       // 创建者
	CreateTime     *gtime.Time `orm:"create_time"      json:"create_time"`     // 创建时间
	UpdateBy       string      `orm:"update_by"        json:"update_by"`       // 更新者
	UpdateTime     *gtime.Time `orm:"update_time"      json:"update_time"`     // 更新时间
	Remark         string      `orm:"remark"           json:"remark"`          // 备注
	TreeCode       string      `json:"tree_code"`                              // 树编码字段
	TreeParentCode string      `json:"tree_parent_code"`                       // 树父编码字段
	TreeName       string      `json:"tree_name"`                              // 树名称字段
	Columns        []*Column   `json:"columns"`                                // 表列信息
	PkColumn       *Column     `json:"pkColumn"`                               // 主键列信息
	Tabs           []*Column   // 在tab页中显示的内容
	Actions        []*Action   // 操作
	IsEmbed        bool        // 是嵌入到其他页面的，不需要注册路由
}

func (t *Table) Print(prefix string) {
	fmt.Println(prefix + t.TableName)
	prefix = prefix + "    "
	fmt.Println(prefix + "[Columns]")
	for _, c := range t.Columns {
		c.Print(prefix)
	}
	fmt.Println(prefix + "[Actions]")
	for _, c := range t.Actions {
		c.Print(prefix)
	}
}

func (t *Table) Copy() *Table {
	bytes, err := json.Marshal(t)
	if err != nil {
		panic(err)
	}
	res := &Table{}
	err = json.Unmarshal(bytes, res)
	if err != nil {
		panic(err)
	}
	return res
}

type Column struct {
	ColumnName       string      `orm:"column_name"        json:"columnName"`       // 列名称
	ColumnComment    string      `orm:"column_comment"     json:"columnComment"`    // 列描述
	ColumnType       string      `orm:"column_type"        json:"columnType"`       // 列类型
	GoType           string      `orm:"go_type"            json:"goType"`           // Go类型
	GoField          string      `orm:"go_field"           json:"goField"`          // Go字段名
	HtmlField        string      `orm:"html_field"         json:"htmlField"`        // html字段名
	IsPk             string      `orm:"is_pk"              json:"isPk"`             // 是否主键（1是）
	IsIncrement      string      `orm:"is_increment"       json:"isIncrement"`      // 是否自增（1是）
	IsRequired       string      `orm:"is_required"        json:"isRequired"`       // 是否必填（1是）
	IsInsert         string      `orm:"is_insert"          json:"isInsert"`         // 是否为插入字段（1是）
	IsEdit           string      `orm:"is_edit"            json:"isEdit"`           // 是否编辑字段（1是）
	IsList           string      `orm:"is_list"            json:"isList"`           // 是否列表字段（1是）
	IsQuery          string      `orm:"is_query"           json:"isQuery"`          // 是否查询字段（1是）
	QueryType        string      `orm:"query_type"         json:"queryType"`        // 查询方式（等于、不等于、大于、小于、范围）
	HtmlType         string      `orm:"html_type"          json:"htmlType"`         // 显示类型（文本框、文本域、下拉框、复选框、单选框、日期控件）
	DictType         string      `orm:"dict_type"          json:"dictType"`         // 字典类型
	Sort             int         `orm:"sort"               json:"sort"`             // 排序
	LinkTableName    string      `orm:"link_table_name"    json:"linkTableName"`    // 关联表名
	LinkTableClass   string      `orm:"link_table_class"   json:"linkTableClass"`   // 关联表类名
	LinkTablePackage string      `orm:"link_table_package" json:"linkTablePackage"` // 关联表包名
	LinkTableModule  string      `orm:"link_table_module"  json:"linkTableModule"`  // 关联表模块
	LinkLabelId      string      `orm:"link_label_id"      json:"linkLabelId"`      // 关联表键名
	LinkLabelName    string      `orm:"link_label_name"    json:"linkLabelName"`    // 关联表字段值
	Immutable        string      // 在输入时不可变的值
	Default          interface{} // 省缺值
	Deliver          string      // 从参数中指定字段读取值
	IsShow           string      // 前端表单动态判断是否显示
}

func (c *Column) Copy() *Column {
	bytes, err := json.Marshal(c)
	if err != nil {
		panic(err)
	}
	res := &Column{}
	err = json.Unmarshal(bytes, res)
	if err != nil {
		panic(err)
	}
	return res
}

func (c *Column) Print(prefix string) {
	fmt.Println(prefix + c.ColumnName + "\t" + c.Immutable)
}

type Assoc struct {
	Model      gjson.Result
	KeyField   string
	LabelField string
	Fields     []string
	Filter     string
	Order      string
}

func (as *Assoc) Parse(json gjson.Result, models map[string]gjson.Result) (isRef bool) {
	if json.IsObject() {
		as = &Assoc{
			Model:      json.Get("model"),
			KeyField:   json.Get("key").String(),
			LabelField: json.Get("label").String(),
			Fields:     nil,
			Filter:     "",
			Order:      "",
		}
		return false
	} else {
		mJson := models[json.String()]
		json = mJson.Get("assoc")
		as = &Assoc{
			Model:      mJson,
			KeyField:   json.Get("key").String(),
			LabelField: json.Get("label").String(),
			Fields:     nil,
			Filter:     "",
			Order:      "",
		}
		return true
	}
}

type Action struct {
	Table      *Table
	Name       string                 // 名字，必须是标识符
	IsValid    string                 // 可用条件
	Type       string                 // 操作类型 "post", "push", "view", "patch", "refer"
	ModuleName string                 // 生成模块名
	Title      string                 // 标题
	Abbr       string                 // 缩写
	Icon       string                 // 图标
	Model      string                 // 目标模型
	Action     string                 // 目标操作
	Deliver    map[string]string      // 传递字段
	Preset     map[string]interface{} // 预设字段
	Exclude    []string               // 排除字段
	Mutable    []string               // 可变字段
	Attributes map[string]interface{} // 属性表
	RowSetting string                 // 可以对单行数据或多行数据操作，为空时表示不是对已有的数据进行的操作 ""/"single"/"multiple"
}

func (ac *Action) Parse(json gjson.Result) {
	if v := json.Get("title"); v.Exists() {
		ac.Title = v.String()
	}
	if v := json.Get("abbr"); v.Exists() {
		ac.Abbr = v.String()
	}
	if v := json.Get("icon"); v.Exists() {
		ac.Icon = v.String()
	}
	if v := json.Get("valid"); v.Exists() {
		ac.IsValid = v.String()
	}
	if v := json.Get("type"); v.Exists() {
		ac.Type = v.String()
	}
	if v := json.Get("model"); v.Exists() {
		ac.Model = v.String()
	}
	if v := json.Get("action"); v.Exists() {
		ac.Action = v.String()
	}
	if v := json.Get("deliver"); v.Exists() && v.IsObject() {
		data := make(map[string]string, 0)
		for key, value := range v.Map() {
			data[key] = value.String()
		}
		ac.Deliver = data
	}
	if v := json.Get("preset"); v.Exists() && v.IsObject() {
		data := make(map[string]interface{}, 0)
		for key, value := range v.Map() {
			data[key] = value.Value()
		}
		ac.Preset = data
	}
	if v := json.Get("exclude"); v.Exists() && v.IsArray() {
		data := make([]string, 0)
		for _, attr := range v.Array() {
			data = append(data, attr.String())
		}
		ac.Exclude = data
	}
	if v := json.Get("mutable"); v.Exists() && v.IsArray() {
		data := make([]string, 0)
		for _, attr := range v.Array() {
			data = append(data, attr.String())
		}
		ac.Mutable = data
	}
	if v := json.Get("attributes"); v.Exists() && v.IsObject() {
		// TODO
	}
}

func (ac *Action) Print(prefix string) {
	fmt.Println(prefix + ac.Name)
	ac.Table.Print(prefix)
}
